package com.fqgj.sentry.policy.engine.eval.script;

import com.fqgj.sentry.common.exception.BizException;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import org.codehaus.groovy.control.CompilationFailedException;
import org.codehaus.groovy.runtime.InvokerHelper;
import com.fqgj.log.interfaces.Log;
import com.fqgj.log.factory.LogFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ScriptEval {


    public static final Log log = LogFactory.getLog(ScriptEval.class);

    private static final Map<String, Script> scriptCache = new ConcurrentHashMap<>();

    /**
     * script有缓存
     *
     * @param normalVar
     * @param script
     * @return
     */
    public static Object evalWithCache(Map normalVar, String script) {

        Object result = null;
        String cacheKey = script.hashCode() + "";
        try {
            Script shell = scriptCache.get(cacheKey);
            if (shell == null) {
                shell = new GroovyShell(ScriptEvalReady.getConfig()).parse(script);
                scriptCache.put(cacheKey, shell);
            }
//            binding并发问题
//            shell.setBinding(ScriptEvalReady.getBinding(normalVar));
//            scriptObject = shell.run();

            result = InvokerHelper.createScript(shell.getClass(), ScriptEvalReady.getBinding(normalVar)).run();

        } catch (Throwable t) {
            log.error("groovy script eval error. script: " + script, t);
        }

        return result;
    }

    /**
     * 不带缓存
     *
     * @param normalVar
     * @param script
     * @return
     */
    public static Object eval(Map normalVar, String script) {

        GroovyShell shell = new GroovyShell(ScriptEvalReady.getBinding(normalVar), ScriptEvalReady.getConfig());
        Object res;
        try {
            res = shell.evaluate(script);
        } catch (CompilationFailedException e) {
            log.error("Compile Error!", e);
            throw new BizException("Compile Error!\n" + e.getMessage(), e);
        } catch (RuntimeException e1) {
            log.error("Eval Runtime Error!", e1);
            throw new BizException("Eval Runtime Error!\n" + e1.getMessage(), e1);
        } catch (Exception e2) {
            log.error("Eval Unknown Error!", e2);
            throw new BizException("Eval Unknown Error!\n" + e2.getMessage(), e2);
        }
        return res;
    }


}
